/*
 * 咩MP3播放器 meMp3Player
 * zyyme 20250404
 * v2.0
 */

package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"strings"
	"time"

	"github.com/gopxl/beep/v2"
	"github.com/gopxl/beep/v2/mp3"
	"github.com/gopxl/beep/v2/speaker"
)

func main() {
	if len(os.Args) < 2 {
		fmt.Println("使用方法：meMp3Player <文件路径/http音频流URL>")
		os.Exit(1)
	}

	input := os.Args[1]
	var streamer beep.StreamSeekCloser
	var format beep.Format
	var err error
	var closeFunc func()

	// 增加http音频流播放支持
	if strings.HasPrefix(input, "http://") || strings.HasPrefix(input, "https://") {
		streamer, format, closeFunc, err = decodeHTTPStream(input)
	} else {
		streamer, format, closeFunc, err = decodeLocalFile(input)
	}

	if err != nil {
		log.Fatal(err)
	}
	defer streamer.Close()

	err = speaker.Init(format.SampleRate, format.SampleRate.N(time.Second/10))
	if err != nil {
		log.Fatal("初始化音频设备失败:", err)
	}

	done := make(chan bool)
	log.Println("开始播放 大小", streamer.Len())
	speaker.Play(beep.Seq(streamer, beep.Callback(func() {
		done <- true
	})))

	// 阻塞等待播放完成
	<-done

	// 统一关闭 回调
	if closeFunc != nil {
		closeFunc()
	}
	log.Println("播放完成")
}

func decodeLocalFile(path string) (beep.StreamSeekCloser, beep.Format, func(), error) {
	log.Println("播放文件", path)

	file, err := os.Open(path)
	if err != nil {
		return nil, beep.Format{}, nil, fmt.Errorf("打开文件失败: %w", err)
	}

	streamer, format, err := mp3.Decode(file)
	if err != nil {
		file.Close()
		return nil, beep.Format{}, nil, fmt.Errorf("解码MP3失败: %w", err)
	}

	return streamer, format, func() { file.Close() }, nil
}

func decodeHTTPStream(url string) (beep.StreamSeekCloser, beep.Format, func(), error) {
	log.Println("播放URL", url)

	client := &http.Client{}
	resp, err := client.Get(url)
	if err != nil {
		return nil, beep.Format{}, nil, fmt.Errorf("HTTP请求失败: %w", err)
	}

	if resp.StatusCode != http.StatusOK {
		resp.Body.Close()
		return nil, beep.Format{}, nil, fmt.Errorf("服务器返回错误状态码: %d", resp.StatusCode)
	}

	streamer, format, err := mp3.Decode(resp.Body)
	if err != nil {
		resp.Body.Close()
		return nil, beep.Format{}, nil, fmt.Errorf("解码MP3流失败: %w", err)
	}

	return streamer, format, func() { resp.Body.Close() }, nil
}
